<?php

namespace app\api\logic;

use app\common\basic\BaseLogic;
use app\common\model\SystemRegion;
use app\api\validate\CustomerValidate;
use app\common\exception\ApiException;
use app\common\model\CrmCustomerAttachment;
use app\common\model\CrmCustomerLogs;
use app\common\model\CrmCustomers;
use app\common\model\CrmCustomerMetas;
use app\common\model\CrmFieldConfigs;
use app\common\model\CrmFollowUps;
use app\common\service\SystemDictService;
use think\facade\Db;
use Webman\Event\Event;

/**
 * 客户逻辑层
 */
class CustomersLogic extends BaseLogic
{
    /**
     * 构造函数
     */
    public function __construct()
    {
        $this->model = new CrmCustomers();
    }

    /**
     * 获取客户列表（包含动态字段）
     * @param array $where
     * @return array
     */
    public function getCustomerList(array $params = [])
    {
        $query = $this->model->hasWhere('metas', function ($query) use ($params) {
            if (!empty($params['name'])) {
                $query->where(function ($query) use ($params) {
                    $query->where('meta_key', 'contact_name')->whereLike('meta_value', "%{$params['name']}%");
                })->whereOr(function ($query) use ($params) {
                    $query->where('meta_key', 'contact_person')->whereLike('meta_value', "%{$params['name']}%");
                });
            }
            if (!empty($params['phone'])) {
                $query->where(function ($query) use ($params) {
                    $query->where('meta_key', 'phone')->whereLike('meta_value', "%{$params['phone']}%");
                })->whereOr(function ($query) use ($params) {
                    $query->where('meta_key', 'wechat')->whereLike('meta_value', "%{$params['phone']}%");
                });
            }
        });
       
        if (!empty($params['province_id'])) {
            $query->where('province_id', $params['province_id']);
        }
        if (!empty($params['city_id'])) {
            $query->where('city_id', $params['city_id']);
        }
        if (!empty($params['area_id'])) {
            $query->where('area_id', $params['area_id']);
        }
        
        if (!empty($params['create_time'])) {
            $query->whereTime('create_time', 'between', $params['create_time']);
        }
        if (!empty($params['user_id'])) {
            $query->where('user_id', $params['user_id']);
        }

        $stateQuery = $query->buildSql(true);
        $state = Db::table($stateQuery)->alias('t')->field('t.stage, count(t.id) as count')->group('t.stage')->select()->toArray();
        
        $stageDict = SystemDictService::getDictData('customer_stage');
        $stageMap = [
            0 => [
                'stage' => 0,
                'title' => '全部',
                'count' => 0,
            ],
        ];
        foreach ($stageDict as $item) {
            $stageMap[$item['value']] = [
                'stage' => $item['value'],
                'title' => $item['label'],
                'count' => 0,
            ];
        }
        foreach ($state as $item) {
            $stageMap[$item['stage']]['count'] = intval($item['count']);
            $stageMap[0]['count'] += intval($item['count']);
        }
        $stageMap = array_values($stageMap);

        if (!empty($params['stage'])) {
            $query->where('stage', $params['stage']);
        }

        $list = $query->with(['follows' => function ($query) {
            $query->order('id desc')->limit(1);
        }, 'user'])->order('id desc')->field('province_id as province, city_id as city, area_id as area')->paginate([
            'list_rows' => $params['limit'],
            'page' => $params['page'],
        ])->each(function ($item) {
            $item['metas'] = $this->getCustomerMetas([$item['id']])[$item['id']] ?? [];
        })->toArray();
        
        $list['stage'] = $stageMap;
        
        return $list;
    }

    /**
     * 获取客户详情（包含动态字段）
     * @param int $id
     * @param string $scene 场景：'view'查看时处理选项值，'edit'编辑时返回原始值
     * @return array|null
     */
    public function getCustomerDetail(int $id, string $scene = 'view')
    {
        $customer = $this->model->with(['metas', 'follows' => function($query) {
            $query->order('id desc')->with(['user', 'partner']);
        }, 'user', 'attachment'])->field('*, province_id as province, city_id as city, area_id as area')->find($id);
        if (!$customer) {
            return null;
        }
        
        $customer = $customer->toArray();
        $customer['metas'] = $this->getCustomerMetas([$id], $scene)[$id] ?? [];
        
        return $customer;
    }

    /**
     * 保存客户（包含动态字段）
     * @param array $data
     * @return array|false
     */
    public function saveCustomer(array $data)
    {
        $allData = $data;
        $validate = new CustomerValidate();
        $validationResult = $validate->validateDynamic($allData, 'save');
        if ($validationResult !== true) {
            throw new ApiException(is_array($validationResult) ? array_shift($validationResult) : $validationResult);
        }
        
        Db::startTrans();
        try {
            $baseData = $this->filterBaseFields($allData);
            $metaData = array_diff_key($allData, $baseData);
            
            // 调试：检查基础数据
            if (empty($baseData)) {
                throw new \Exception('保存客户失败：没有有效的基础字段数据');
            }
            
            // 4. 保存数据
            $customer = new CrmCustomers();
            $result = $customer->save($baseData);
            
            // 调试信息
            if (!$result) {
                throw new \Exception('保存客户失败：数据库操作失败');
            }
            
            // 确保获取到插入的ID
            $customerId = $customer->id;
            if (!$customerId) {
                // 尝试通过最后插入ID获取
                $customerId = $customer->getLastInsID();
            }
            
            if (!$customerId) {
                throw new \Exception('保存客户失败：无法获取客户ID');
            }
            
            // 保存动态字段
            if (!empty($metaData)) {
                $processedMetaData = $this->processMetaData($metaData);
                $this->saveCustomerMetas($customerId, $processedMetaData);
            }
            
            // 触发事件
            Event::emit('customer.changed', [
                'customerId' => $customerId,
                'eventType' => '新增客户',
                'originalCustomerData' => [],
                'newCustomerData' => $baseData ?? [],
                'originalMetasData' => [],
                'newMetasData' => $metaData ?? [],
            ]);
            
            Db::commit();
            return $this->getCustomerDetail($customerId);
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
    }

     /**
     * 更新客户（包含动态字段）
     * @param int   $id
     * @param array $data
     * @return array|false
     */
    public function updateCustomer(int $id, array $data)
    {
        $validate = new CustomerValidate();
        $validationResult = $validate->validateDynamic($data, 'update');
        if ($validationResult !== true) {
            throw new ApiException(is_array($validationResult) ? array_shift($validationResult) : $validationResult);
        }

        Db::startTrans();
        try {
            $customer = CrmCustomers::findOrFail($id);
            if (!$customer) {
                throw new \Exception('客户不存在');
            }
            $originalCustomerData = $customer->toArray();
            // 获取原始动态字段
            $originalMetas = CrmCustomerMetas::where('customer_id', $id)->select()->toArray();
            $originalMetasData = [];
            foreach ($originalMetas as $meta) {
                $originalMetasData[$meta['meta_key']] = $meta['meta_value'];
            }

            $baseData = $this->filterBaseFields($data, 'update');
            $metaData = array_diff_key($data, $baseData);
            // 更新基础字段
            if (!empty($baseData)) {
                $customer->save($baseData);
            }

            // 更新动态字段
            if (!empty($metaData)) {
                $processedMetaData = $this->processMetaData($metaData);
                $this->saveCustomerMetas($id, $processedMetaData);
            }

            // 触发事件
            Event::emit('customer.changed', [
                'customerId' => $id,
                'eventType' => '更新客户',
                'originalCustomerData' => $originalCustomerData,
                'newCustomerData' => $baseData ?? [],
                'originalMetasData' => $originalMetasData,
                'newMetasData' => $metaData ?? [],
            ]);

            Db::commit();
            return $this->getCustomerDetail($id, 'edit');
        } catch (\Exception $e) {
            Db::rollback();
            throw new \Exception('更新客户失败：' . $e->getMessage());
        }
        
    }


    /**
     * 处理元数据
     * @param array $metaData 元数据
     * @return array 处理后的元数据
     */
    protected function processMetaData(array $metaData): array
    {
        $processed = [];
        
        foreach ($metaData as $key => $value) {
            // 处理数组值（如复选框）
            if (is_array($value)) {
                $value = json_encode($value, JSON_UNESCAPED_UNICODE);
            }
            $processed[$key] = $value;
        }
        
        return $processed;
    }

    /**
     * 删除客户（同时删除动态字段）
     * @param int $id
     * @return bool
     */
    public function deleteCustomer(int $id): bool
    {
        Db::startTrans();
        try {
            $customer = $this->model->find($id);
            if (!$customer) {
                return false;
            }
            
            // 删除客户
            $customer->delete();
            
            // 删除动态字段
            CrmCustomerMetas::where('customer_id', $id)->delete();
            
            // 删除客户关联的跟进记录
            CrmFollowUps::where('customer_id', $id)->delete();

            // 删除客户关联的附件
            CrmCustomerAttachment::where('customer_id', $id)->delete();

            // 删除日志
            CrmCustomerLogs::where('customer_id', $id)->delete();

            // 触发事件
            Event::emit('customer.changed', [
                'customerId' => $id,
                'eventType' => '删除客户',
                'description' => '删除客户',
                'diff' => [],
            ]);
            
            Db::commit();
            return true;
        } catch (\Exception $e) {
            Db::rollback();
            return false;
        }
    }

    /**
     * 改变客户状态
     * @param int $id
     * @return bool
     */
    public function changeStatus(int $id): bool
    {
        $customer = $this->model->find($id);
        if (!$customer) {
            return false;
        }

        $customer->status = $customer->status == 1 ? 2 : 1;
        return $customer->save();
    }

    /**
     * 获取客户动态字段值
     * @param array $customerIds
     * @param string $scene 场景：'view'查看时处理选项值，'edit'编辑时返回原始值
     * @return array
     */
    protected function getCustomerMetas(array $customerIds, string $scene = 'view'): array
    {
        $metas = CrmCustomerMetas::whereIn('customer_id', $customerIds)
            ->select()
            ->toArray();
        
        $result = [];
        foreach ($metas as $meta) {
            $result[$meta['customer_id']][$meta['meta_key']] = $meta['meta_value'];
        }
        
        // 如果不是查看场景，直接返回原始值
        if ($scene === 'edit') {
            return $result;
        }
        
        // 获取字段配置信息用于处理选项值
        $fieldConfigs = $this->getFieldConfigs();
        
        // 处理选项字段，将值转换为label
        foreach ($result as $customerId => &$metasData) {
            foreach ($metasData as $fieldName => &$fieldValue) {
                if ($fieldName == 'intent_score') {
                    $fieldValue = 1 * $fieldValue;
                }
                if (isset($fieldConfigs[$fieldName]) && !empty($fieldConfigs[$fieldName]['options'])) {
                    $fieldConfig = $fieldConfigs[$fieldName];
                    $options = $this->parseOptions($fieldConfig['options']);
                    
                    // 处理多选字段（checkbox）
                    if ($fieldConfig['type'] === 'checkbox' && is_string($fieldValue)) {
                        $selectedValues = explode(',', $fieldValue);
                        if (!is_array($selectedValues)) {
                            $selectedValues = [$fieldValue];
                        }
                        $labels = [];
                        foreach ($selectedValues as $value) {
                            if (is_string($value) || is_numeric($value)) {
                                $labels[] = $options[$value] ?? (string)$value;
                            }
                        }
                        $fieldValue = implode(', ', $labels);
                    }
                    // 处理单选字段
                    elseif (is_string($fieldValue) || is_numeric($fieldValue)) {
                        $fieldValue = $options[$fieldValue] ?? (string)$fieldValue;
                    }
                }
            }
        }
        
        return $result;
    }

    /**
     * 保存客户动态字段（增量更新/删除，不再整表 truncate）
     * @param int   $customerId
     * @param array $metaData
     */
    protected function saveCustomerMetas(int $customerId, array $metaData): void
    {
        foreach ($metaData as $key => $value) {
            if ($value === null) {
                // 删除该 key
                CrmCustomerMetas::where([
                    'customer_id' => $customerId,
                    'meta_key'    => $key,
                ])->delete();
            } else {
                // 新增或覆盖
                CrmCustomerMetas::updateOrCreate([
                    'customer_id' => $customerId,
                    'meta_key'    => $key,
                ], [
                    'meta_value'  => $value,
                ]);
            }
        }
    }

    /**
     * 获取字段配置信息
     * @return array
     */
    protected function getFieldConfigs(): array
    {
        $fields = CrmFieldConfigs::field(['name', 'type', 'options', 'label'])
            ->select()
            ->toArray();
            
        $configs = [];
        foreach ($fields as $field) {
            $configs[$field['name']] = $field;
        }
        
        return $configs;
    }

    /**
     * 解析选项数据
     * @param string|array $options
     * @return array
     */
    protected function parseOptions($options): array
    {
        if (empty($options)) {
            return [];
        }
        
        if (is_string($options)) {
            $options = json_decode($options, true);
        }
        
        if (!is_array($options)) {
            return [];
        }
        
        $parsed = [];
        foreach ($options as $option) {
            if (isset($option['value'], $option['label'])) {
                $parsed[$option['value']] = $option['label'];
            }
        }
        
        return $parsed;
    }

    /**
     * 过滤基础字段
     * @param array $data
     * @return array
     */
    protected function filterBaseFields(array $data, string $scene = 'create'): array
    {
        $baseFields = [
            'stage' => 1,      // 默认阶段
            'status' => 1,     // 默认状态
            'province_id' => 0, // 省份ID
            'city_id' => 0,    // 城市ID
            'area_id' => 0,    // 区县ID
            'user_id' => 0,    // 负责人ID
            'lat' => 0,        // 纬度
            'lng' => 0,        // 经度
        ];
        
        $result = [];
        if ($scene !== 'update') {
            foreach ($baseFields as $field => $defaultValue) {
                // 如果数据中存在该字段，使用传入的值，否则使用默认值
                $result[$field] = $data[$field] ?? $defaultValue;
            }
        }
        
        if (empty($result['area_id']) && !empty($data['region'])) {
            $result['area_id'] = $data['region'];
        }
        if (!empty($result['area_id']) && (empty($result['city_id']) || empty($result['province_id']))) {
            $result['city_id'] = SystemRegion::where('id', $result['area_id'])->value('parent_id');
            if (!empty($result['city_id'])) {
                $result['province_id'] = SystemRegion::where('id', $result['city_id'])->value('parent_id');
            }
        }
        
        return $result;
    }
    
    /**
     * 以分组形式返回客户信息
     */
    public function getCustomerInfo(int $id, string $scene = '')
    {
        $customerInfo = $this->getCustomerDetail($id, $scene);
        if (!$customerInfo) {
            return false;
        }
        
        //处理metas字段, 按照分组形式返回
        $settingsLogic = new CrmSettingsLogic();
        $fieldGroups = $settingsLogic->getGroupsWithFields();
        $metas = [];
        foreach ($fieldGroups as $group) {
            $fields = [];
            foreach ($group['fields'] as $field) {
                $fields[$field['name']] = [
                    'name' => $field['name'],
                    'label' => $field['label'],
                    'value' => $customerInfo['metas'][$field['name']] ?? '',
                ];
            }
            $group['fields'] = $fields;
            $metas[$group['name']] = $group;
        }
        $customerInfo['metas'] = $metas;

        return $customerInfo;
    }
}
